/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.uoc.tfc.exuoc.model;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Inheritance;
import javax.persistence.JoinColumn;
import javax.persistence.Version;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.JoinTable;

import java.util.Date;
import java.util.List;
import java.util.ArrayList;

import edu.uoc.tfc.exuoc.config.Config;
import edu.uoc.tfc.exuoc.controladors.GestorLogs ;
import org.hibernate.annotations.Cascade;
/**
 *
 * @author emoreno
 */
@Entity
@Table(name="items")
//@PrimaryKeyJoinColumn(name="id")
//@Inheritance(strategy = javax.persistence.InheritanceType.JOINED)

//    uniqueConstraints={@UniqueConstraint(columnNames="nom")})
public class Item implements  InterfaceItem, Serializable, Comparable {
    private static final long serialVersionUID = 4356342345L;
    private Long id=Config.valorNull;
    private String nom=Config.valorNullStr;
    private Date datapub=new Date();
    private String descripcio=Config.valorNullStr;
    private Boolean privat=false;
    
    private Integer visites=Config.valorNullInt;
    private String autor=Config.valorNullStr;

    //E-R amb l'arxiu de l'ítem 1 a 1
    private Arxiu arxiu=null;

     // E-R Quin contenidor conté aquest ítem
    private Contenidor contenidor;

    // E-R amb Items
   //16-01-2012:Emili: private List<MetaDC> metesDC=new ArrayList<MetaDC>(0);
    List<MetadadaDetall> metadadesDetalls = new ArrayList<MetadadaDetall>();

    //Control de versió
    private int versionNum=Config.valorNullInt;

    public Item(){};
    //TODO: 07-12-2011: Emili:  mirar de treure les dates com a dades de recollida
    //                          ja que la base de dades té aquest valor com a
    //                          valor per defecte.
    /**
     * 
     * @param _nom
     * @param _data
     * @param _descripcio
     * @param _privat
     * @param _contenidor
     * @param _arxiu
     */
     public Item(String _nom,Date _data,String _descripcio, Boolean _privat,
            Contenidor _contenidor){
        this.nom=_nom;
        this.datapub=_data;
        this.descripcio=_descripcio;
        this.privat=_privat;
        this.contenidor=_contenidor;
        this.visites=0;
        this.autor="ExUOC";
        this.arxiu=new Arxiu();
    }

    public Item(String _nom,Date _data,String _descripcio, Boolean _privat,
            Contenidor _contenidor, Arxiu _arxiu){
        this.nom=_nom;
        this.datapub=_data;
        this.descripcio=_descripcio;
        this.privat=_privat;
        this.contenidor=_contenidor;
        this.visites=0;
        this.autor="ExUOC";
        this.arxiu=_arxiu;
    }
    /**
     * 
     * @param _nom
     * @param _data
     * @param _descripcio
     * @param _privat
     * @param _visites
     * @param _autor
     * @param _contenidor
     * @param _arxiu
     */
    public Item(String _nom,Date _data,String _descripcio, Boolean _privat,
            Integer _visites, String _autor, Contenidor _contenidor,
            Arxiu _arxiu){
        this.nom=_nom;
        this.datapub=_data;
        this.descripcio=_descripcio;
        this.privat=_privat;
        this.contenidor=_contenidor;
        this.visites=_visites;
        this.autor=_autor;
        this.arxiu=_arxiu;
    }
    /**
     *
     * @param _id
     * @param _nom
     * @param _data
     * @param _descripcio
     * @param _privat
     * @param _visites
     * @param _autor
     * @param _contenidor
     * @param _arxiu
     */
    public Item(Long _id, String _nom,Date _data,String _descripcio, 
            Boolean _privat, Integer _visites, String _autor,
            Contenidor _contenidor, Arxiu _arxiu){
        this.id=_id;
        this.nom=_nom;
        this.datapub=_data;
        this.descripcio=_descripcio;
        this.privat=_privat;
        this.contenidor=_contenidor;
        this.visites=_visites;
        this.autor=_autor;
        this.arxiu=_arxiu;
    }




    @Id
    @SequenceGenerator(name="items", sequenceName="seqitems")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="items")
    @Override
    
    public Long getId(){
        return id;
    }
    @Column(length=255,nullable=false,unique=true)
    @Override
    
    public String getNom(){
        return nom;
    }
    @Temporal(javax.persistence.TemporalType.DATE)
    @Column(nullable=false)
    @Override
    
    public Date getDatapub(){
        return datapub;
    }
    @Column(length=255)
    @Override
    
    public String getDescripcio() {
        return descripcio;
    }

    
    @Override
    public Boolean isPrivat() {
        return privat;
    }
    
    public Boolean getPrivat() {
        return this.isPrivat();
    }
  
    @Override
    public Integer getVisites() {
        return visites;
    }

    @Column(length=255,nullable=false)
    @Override
    
    public String getAutor() {
        return autor;
    }
    // Control d'exceptions :StaleObjectStateException
    @Version
    @Column(name="version", nullable=true)
    protected int getVersionNum() {
        return versionNum;
    }

    /* Classe incrustada dintre de la mateixa taula Items
     * Nom indica el nom de l'arxiu a la classe Arxiu, i que a la taula Items
     * apareix com a nomArxiu
     */

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="nom",column=@Column(name="nomArxiu"))})    
    @Override
    
    public Arxiu getArxiu() {
        return arxiu;
    }
   
    @ManyToOne
    
    @JoinColumn(name="contenidor_id")
    @Override
    public Contenidor getContenidor() {
        return this.contenidor;
    }

    
    @Override
    public void setContenidor(Contenidor contenidor) {
        this.contenidor = contenidor;
    }


    @OneToMany(fetch = javax.persistence.FetchType.LAZY, mappedBy = "pk.item",
    cascade ={javax.persistence.CascadeType.PERSIST,
        javax.persistence.CascadeType.MERGE})
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
    org.hibernate.annotations.CascadeType.DELETE_ORPHAN})

    @Override
    public List<MetadadaDetall> getMetadadesDetalls() {
        return metadadesDetalls;
    }

    @Override
    public void setMetadadesDetalls(List<MetadadaDetall> _metadadesDetalls) {
        this.metadadesDetalls = _metadadesDetalls;
    }

      public void addMetaDC(MetaDC metaDC, String valorDC) {
        MetadadaDetall associacio = new MetadadaDetall();
        associacio.setItem(this);
        associacio.setMetaDC(metaDC);
        associacio.setValor(valorDC);

        this.metadadesDetalls.add(associacio);
        metaDC.getMetadadesDetalls().add(associacio);
    }

    public void delItem(MetaDC metaDC){
        MetadadaDetall associacio = new MetadadaDetall();
        associacio.setItem(this);
        associacio.setMetaDC(metaDC);

        this.metadadesDetalls.remove(associacio);
        metaDC.getMetadadesDetalls().remove(associacio);
    }

/* 16-01-2012:Emili
    @ManyToMany(cascade=javax.persistence.CascadeType.ALL)
    //Emili:11-01-2012,    fetch=javax.persistence.FetchType.EAGER)
    @JoinTable(
        name="metadades_detalls",
        joinColumns={@JoinColumn(name="iditem")},
        inverseJoinColumns={@JoinColumn(name="iddublincore")}
    )
   // @SequenceGenerator(name="metadades_detalls",
   //                    sequenceName="seqmetadades_detalls")
   // @GeneratedValue(strategy=GenerationType.SEQUENCE,
   //                 generator="seqmetadades_detalls")
   //



    @Override

    public List<MetaDC> getMetesDC() {
        return metesDC;
    }

    @Override
    public void setMetesDC(List<MetaDC> _metesDC) {
        this.metesDC = _metesDC;
    }

    public void addMetaDC(MetaDC _metaDC)
    {
        //Ja la tenim ?
        if ( ! this.metesDC.contains(_metaDC))
            this.metesDC.add((MetaDC)_metaDC);
    }

    public void delMetaDC(MetaDC _metaDC)
    {
        //Existeix la metadada?
        if (this.metesDC.contains(_metaDC))
            this.metesDC.remove(_metaDC);
    }
*/
    @Override
    public void setId(Long _id){
        this.id=_id;
    }
    
    @Override
    public void setNom(String _nom){
        this.nom=_nom;
    }
    
    @Override
    public void setDatapub(Date _data){
        this.datapub=_data;
    }

    
    @Override
    public void setArxiu(Arxiu arxiu) {
        this.arxiu = arxiu;
    }

    
    @Override
    public void setDescripcio(String descripcio) {
        this.descripcio = descripcio;
    }

    
    @Override
    public void setPrivat(Boolean privat) {
        this.privat = privat;
    }

    @Override
    public void setVisites(Integer visites) {
        this.visites = visites;
    }
   
    @Override
    public void setAutor(String autor) {
        this.autor = autor;
    }
    
    protected void setVersionNum(int versionNum) {
        this.versionNum = versionNum;
    }

    
    @Override
    public String toString(){
        String cad="";
        if (this.id != null ){
            cad=this.id+": ";
        }
        if (this.nom != null ){
            cad=cad.concat(this.getNom()+": ");
        }

        if (this.datapub != null ){
            cad=cad.concat(this.getDatapub().toString());
        }
        return cad;
    }

   @Override
     public int compareTo(Object o) {
        if (o == null) {
            return -1;
        }
        return (this.equals(o))? 0:1;
    }




   @Override
    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
    public boolean equals(Object obj) {
        Item other;
        try {
            if (obj == null) {
                GestorLogs .getLogger(this.getClass().getSimpleName())
                        .info("Item:Objecte null a comparar");
                return false;
            }else {
                other = (Item)obj;
            }
            if (!this.getId().equals(other.getId())) {
                return false;
            }

            if (!this.nom.trim().equals(other.getNom().trim())) {
                return false;
            }
        }catch(ClassCastException e){
            return false;
        }catch(NullPointerException e){
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 67 * hash + (this.getId() != null ? this.getId().hashCode() : 0);
        hash = 67 * hash + (this.nom != null ? this.nom.hashCode() : 0);
        hash = 67 * hash + (this.autor != null ? this.autor.hashCode() : 0);
        hash = 67 * hash + (this.datapub != null ? this.datapub.hashCode() : 0);
        return hash;


    }

}
